import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectOutputStream;
import java.io.Reader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Hashtable;
import java.util.LinkedList;

import javax.swing.text.html.HTMLEditorKit.ParserCallback;
import javax.swing.text.html.parser.ParserDelegator;

/**
 * @description
 * 
 * @author vihuynh, k7ho
 * 
 */
public class Index {	
	
	final static String ERR_URL = "%s is not a valid absolute URL.\n";
	final static String MSG_USAGE = "Usage: %s firstpage depth|breadth maxpages indexfile\n";
	final static String MSG_START = "Doing a %s-first search of the Web, starting from \n%s\n";
	
	private static Hashtable<String, Hashtable<String,Integer>> hashTbl; // hold the data structure
	static LinkedList<String> urlLinks = new LinkedList<String>();
	static LinkedList<String> visitedLinks = new LinkedList<String>();
	LinkedList<Integer> urlWords = new LinkedList<Integer>();
	
	private String[] args;
	private String start ="";
	private static int maxPage = 0 ;
	private static boolean breadth = true;  // t-breadth-first f- depth-first 
	
	public Index (String[] args){
		hashTbl = new Hashtable<String,Hashtable<String,Integer>>();
		this.args = args;
		start = args[0];
		maxPage = new Integer(args[2]); 
	}
	
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {		
		/***TESTING***********************************************/
		//System.err.println(" args size"+args.length);
		/***TESTING***********************************************/
		
		if (args.length < 4 || new Integer(args[2]) < 0) {
			System.out.printf(MSG_USAGE, Index.class.getName());
			return;
		}		
		
		//String urlLink = args[1];
		try {
			Index index = new Index(args);			
			
			String readingURL = args[0];	
			
			if (args[1].equals("depth")) {
				breadth = false;
			} 
			
			do{
				index.readHTML(readingURL);				
				if (!urlLinks.isEmpty() ) {
					if ( breadth ) {					
						readingURL = urlLinks.removeFirst();  
					}
					else{
						readingURL = urlLinks.removeLast();
					}
				} else {
					break;
					
				}
				/***TESTING***********************************************/
				//System.err.println(urlLinks.size() + " * "+ visitedLinks.size());
				/***TESTING***********************************************/
			}while (  visitedLinks.size() < maxPage  );
			
			//	Hashtable<String,Hashtable<String,Integer>> bigTbl = hashTbl;
			index.writeFile(hashTbl, args[3]);
			
		} catch (Exception e) {
			// user input not valid URL
			System.out.printf(ERR_URL, args[0]);
			System.out.printf(MSG_USAGE, Index.class.getName());
			e.printStackTrace();
		}

	}

	private void readHTML(String urlLink)
			throws MalformedURLException, IOException {
		
		if ( visitedLinks.contains(urlLink)) {
			return;	
		}
		
		URL myURL = new URL(urlLink);
		ParserCallback myParser = new NewParserCallBack(myURL, hashTbl);

		Reader myReader = new BufferedReader(new InputStreamReader(myURL
				.openStream()));

		ParserDelegator pDelegator = new ParserDelegator();
		pDelegator.parse(myReader, myParser, true);
		// TODO while loop if the queue/
		// Vincent do the "DEPTH" searching

		visitedLinks.add(urlLink);
		urlWords.add(((NewParserCallBack) myParser).wordCount);		
		urlLinks.addAll( ((NewParserCallBack) myParser).getList() );
		for(String anchorWord : ((NewParserCallBack) myParser).getList2()) {
			if(hashTbl.containsKey(anchorWord)){
				
			}
			else {
				Hashtable<String, Integer> smallTbl = new Hashtable<String,Integer>();
				//add next urlLink to smallTbl
				/***************WORK HERE WTF???!!!!***************************/
				//hashTbl.put(anchorWord, );
			}
		}
		
		/***TESTING***********************************************/
		System.out.println(urlLink + " " + "(" + 
				          ((NewParserCallBack) myParser).wordCount + ")");
		//Hashtable t =  ((NewParserCallBack) myParser).getHashHits();
		//System.err.println(((NewParserCallBack) myParser).wordCount);
//		Keyword key = new Keyword();
//		System.err.println(hashTbl.get( key.makeKeyword("become")) );		
		/***TESTING***********************************************/
	}
	
	public void writeFile (Hashtable<String, Hashtable<String,Integer>> hashTbl, String fileName) {
		try {
			
			BufferedOutputStream bos = new BufferedOutputStream (new FileOutputStream( fileName) );
			ObjectOutputStream oos = new ObjectOutputStream(bos);
			
			System.out.println("Writing hashtable to " + fileName);
			
			oos.writeObject(hashTbl);
			
			bos.close();
			oos.close();
			
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}
